package com.library.system.controller;

import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.CharsetUtil;
import cn.hutool.crypto.digest.DigestUtil;
import cn.hutool.http.Header;
import cn.xuyanwu.spring.file.storage.FileInfo;
import cn.xuyanwu.spring.file.storage.FileStorageService;
import cn.xuyanwu.spring.file.storage.exception.FileStorageRuntimeException;
import com.library.common.annotation.CurrentUser;
import com.library.common.enums.ErrorCodeEnum;
import com.library.common.service.bo.CurrentLoginUser;
import com.library.logging.annotation.LogSys;
import com.library.system.modules.file.bo.UploadFileBO;
import com.library.system.modules.file.vo.FileVO;
import com.library.system.modules.file.bo.FilePage;
import com.library.system.modules.file.service.FileService;
import com.library.system.modules.file.vo.UploadFileInfoVO;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.log4j.Log4j2;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.library.common.response.Result;
import jakarta.annotation.Resource;
import jakarta.validation.Valid;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
import java.net.URLEncoder;


/**
 * @Author xyh
 * @Desc 文件表(File)表控制层
 * @Date 2023-09-10 08:58:34
 */

@Log4j2
@RestController
@RequestMapping("file")
public class FileController {

    @Resource
    private FileService fileService;
    @Resource
    private FileStorageService fileStorageService;


    /**
     * 分页查询列表
     *
     * @return 数据
     */
    @LogSys(value = "文件分页查询列表")
    @GetMapping("/list")
    public Result<IPage<FileVO>> queryByPage(@Valid FilePage page) {
        return Result.success(fileService.queryByPage(page));
    }

    /**
     * 根据ID获取数据
     *
     * @return 单个文件表数据
     */
    @LogSys(value = "单个文件表数据")
    @PostMapping("/queryById/{id}")
    public Result<FileVO> queryById(@PathVariable("id") Integer id) {
        return Result.success(fileService.queryById(id));
    }

    /**
     * 删除文件表
     *
     * @return 删除文件表数据
     */
    @LogSys(value = "删除文件表数据")
    @DeleteMapping("/delete/{id}")
    public Result deleteById(@PathVariable("id") Integer id) {
        fileService.deleteById(id);
        return Result.success();
    }

    /**
     * 上传图片
     * @param file
     * @return
     */
    @LogSys(value = "上传图片")
    @PostMapping("/upload")
    public Result<UploadFileInfoVO> uploadImg(@PathVariable("file") MultipartFile file,
                                              @Valid UploadFileBO bo,
                                              @CurrentUser CurrentLoginUser currentLoginUser) throws IOException {
        if (file == null) {
            return Result.error(ErrorCodeEnum.FILE_NONE.getCode(), "上传的文件为空");
        }
        bo.setUsername(currentLoginUser.getUsername());
        //检测图片存不存在
        String sign = DigestUtil.md5Hex(file.getBytes());
        FileVO vo = fileService.getFileBySign(sign);
        if (vo == null) {
            bo.setFileSign(sign);
            //上传
            vo = fileService.upload(file, bo);
        }
        UploadFileInfoVO infoVO = UploadFileInfoVO.builder()
                .filename(vo.getStorageFilename())
                .url(vo.getUrl())
                .build();

        return Result.success(infoVO);
    }

    /**
     * 下载图片
     * @param response
     * @return
     */
    @LogSys(value = "下载图片")
    @GetMapping("/download/{id}")
    public void download(@PathVariable("id") Integer id, HttpServletResponse response) throws IOException {
        FileVO vo = fileService.queryById(id);
        byte[] fileBytes = null;
        if (fileService.isLocalPlatform(vo.getStoragePlatform())) {
            FileInfo fileInfo = fileVOtoFileInfo(vo);
            try {
                fileBytes = fileStorageService.download(fileInfo).bytes();
            } catch (FileStorageRuntimeException e) {
                log.error("文件下载失败，文件名：{}, 错误信息：", vo.getStorageFilename(), e);
            }
        } else {
            // 执行302重定向，将用户重定向到外部URL
            response.sendRedirect(vo.getUrl());
            return;
        }
        //下载
        response.setHeader(Header.CONTENT_TYPE.getValue(), MediaType.APPLICATION_OCTET_STREAM_VALUE);
        response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
        String downFileName = URLEncoder.encode(vo.getStorageFilename(), CharsetUtil.UTF_8);
        response.setHeader(Header.CONTENT_DISPOSITION.getValue(), "attachment;filename=" + downFileName);
        IoUtil.write(response.getOutputStream(), false, fileBytes);
    }

    private FileInfo fileVOtoFileInfo(FileVO vo) {
        FileInfo fileInfo = new FileInfo();
        fileInfo.setPlatform(vo.getStoragePlatform());
        fileInfo.setBasePath(vo.getBasePath());
        fileInfo.setPath(vo.getStoragePath());
        fileInfo.setSize(vo.getFileSize());
        fileInfo.setFilename(vo.getStorageFilename());
        fileInfo.setOriginalFilename(vo.getOriginalFilename());
        return fileInfo;
    }

}
